package com.eian.boot.module.system.associations.role.permission.service;

import com.eian.boot.module.system.associations.role.permission.event.PermissionUnassignedEvent;
import com.eian.boot.module.system.associations.role.permission.event.RolePermissionAssignedEvent;
import com.eian.boot.module.system.associations.role.permission.mapper.RolePermissionMapper;
import com.eian.boot.module.system.associations.role.permission.model.entity.SysRolePermissionEntity;
import com.eian.boot.mybatis.core.service.BaseService;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

import static com.eian.boot.table.Tables.sys_role_permission;

/**
 * 角色权限关系管理服务
 * 职责：纯粹的关系数据管理，不包含业务逻辑验证
 *
 * @author alex.meng
 * @since 1.0.0
 */
@Slf4j
@Service
public class RolePermissionRelationService extends BaseService<RolePermissionMapper, SysRolePermissionEntity> {

    private final ApplicationEventPublisher eventPublisher;

    public RolePermissionRelationService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    /**
     * 分配角色权限
     * 先清除旧关系，再建立新关系
     *
     * @param roleId        角色ID
     * @param permissionIds 权限ID列表
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean assignRolePermissions(Long roleId, List<Long> permissionIds) {
        log.debug("分配角色权限: roleId={}, permissionIds={}", roleId, permissionIds);

        // 清除旧关系
        this.remove(QueryWrapper.create()
                .from(sys_role_permission)
                .where(sys_role_permission.role_id.eq(roleId)));

        // 建立新关系
        if (permissionIds != null && !permissionIds.isEmpty()) {
            List<SysRolePermissionEntity> relations = permissionIds.stream()
                    .map(permId -> SysRolePermissionEntity.builder()
                            .roleId(roleId)
                            .permissionId(permId)
                            .build())
                    .collect(Collectors.toList());
            boolean result = this.saveBatch(relations);

            // 发布领域事件
            if (result) {
                eventPublisher.publishEvent(new RolePermissionAssignedEvent(this, roleId, permissionIds));
            }
            return result;
        }

        // 清空权限也发布事件
        eventPublisher.publishEvent(new RolePermissionAssignedEvent(this, roleId, List.of()));
        return true;
    }

    /**
     * 查询角色的权限ID列表
     *
     * @param roleId 角色ID
     * @return 权限ID列表
     */
    public List<Long> getPermissionIdsByRoleId(Long roleId) {
        return this.queryChain()
                .select(sys_role_permission.permission_id)
                .from(sys_role_permission)
                .where(sys_role_permission.role_id.eq(roleId))
                .listAs(Long.class);
    }

    /**
     * 查询权限关联的角色ID列表
     *
     * @param permissionId 权限ID
     * @return 角色ID列表
     */
    public List<Long> getRoleIdsByPermissionId(Long permissionId) {
        return this.queryChain()
                .select(sys_role_permission.role_id)
                .from(sys_role_permission)
                .where(sys_role_permission.permission_id.eq(permissionId))
                .listAs(Long.class);
    }

    /**
     * 检查权限是否有角色绑定
     *
     * @param permissionId 权限ID
     * @return true-有绑定，false-无绑定
     */
    public boolean checkPermissionHasRoles(Long permissionId) {
        return this.queryChain()
                .from(sys_role_permission)
                .where(sys_role_permission.permission_id.eq(permissionId))
                .exists();
    }

    /**
     * 级联删除：当角色被删除时调用
     * 清理角色的所有权限关系
     *
     * @param roleId 角色ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void cascadeDeleteByRoleId(Long roleId) {
        log.debug("级联删除角色权限关系: roleId={}", roleId);

        // 删除关系
        this.remove(QueryWrapper.create()
                .from(sys_role_permission)
                .where(sys_role_permission.role_id.eq(roleId)));
    }

    /**
     * 级联删除：当权限被删除时调用
     * 清理权限与所有角色的关系
     *
     * @param permissionId 权限ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void cascadeDeleteByPermissionId(Long permissionId) {
        log.debug("级联删除权限角色关系: permissionId={}", permissionId);

        // 先查询要删除的角色ID（用于事件通知）
        List<Long> roleIds = this.getRoleIdsByPermissionId(permissionId);

        // 删除关系
        this.remove(QueryWrapper.create()
                .from(sys_role_permission)
                .where(sys_role_permission.permission_id.eq(permissionId)));

        // 发布事件
        if (!roleIds.isEmpty()) {
            eventPublisher.publishEvent(new PermissionUnassignedEvent(this, permissionId, roleIds));
        }
    }
}

